/**
 * HttpUtilImpl.java<br>
 * 
 * @author aaronwong.sd@foxmail.com
 * @version 下午3:23:55
 */
package com.iwechat.httpClient;

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.iwechat.PropertyUtils;
import com.iwechat.api.http.ConstEmus;

/**
 * http工具类
 * 
 * @author aaronwong.sd@foxmail.com
 */
public class HttpUtilImpl implements IHttpUtil {
    /** logger */
    private static final Logger     logger   = LoggerFactory.getLogger(IHttpUtil.class);
    private static final HttpUtilImpl instance = new HttpUtilImpl();
    private HttpClient            client   = HttpClient.getInstance();
    private PropertyUtils           util     = PropertyUtils.getInstance();

    private String                  charset;

    public static HttpUtilImpl getInstance() {
        return instance;
    }

    private HttpUtilImpl() {
        charset = util.getStringValue("settings", "charset");
        logger.info("### init succeed!");
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.iwechat.api.http.IHttpUtil#sendPost(java.lang.String, java.lang.String, java.lang.String)
     */
    @Override
    public String sendPost(String url, String data, String sequence) throws Exception {
        String retStr = "{}";
        long begin = System.currentTimeMillis();
        CloseableHttpResponse response = null;
        try {
            StringBuffer logbuf = new StringBuffer();
            logbuf.append(sequence);
            logbuf.append(" send_post_to : ");
            logbuf.append(url);
            logbuf.append("; ");
            logbuf.append("send_data : ");
            logbuf.append(data);
            logger.info(logbuf.toString());

            HttpPost httpPost = new HttpPost(url);
            HttpEntity entity = new StringEntity(data, charset);
            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            StatusLine statusLine = response.getStatusLine();
            if (HttpStatus.SC_OK == statusLine.getStatusCode()) {
                HttpEntity re = response.getEntity();
                retStr = EntityUtils.toString(re, charset);
                retStr = retStr == null ? "" : retStr.trim();
            } else {
                JSONObject respJson = this.getJsonerrcode(statusLine);
                respJson.put(ConstEmus.sequence.value(), sequence);
                retStr = respJson.toJSONString();
            }

            logbuf = new StringBuffer();
            logbuf.append(sequence);
            logbuf.append(" response_status : ");
            logbuf.append(statusLine.getStatusCode());
            logbuf.append("; ");
            logbuf.append("consuming_time : ");
            logbuf.append(System.currentTimeMillis() - begin);
            logbuf.append(" ms; ");
            logbuf.append("recive_data : ");
            logbuf.append(retStr);
            logger.info(logbuf.toString());
        } catch (IOException e) {
            throw new HttpException("HttpUtilImpl throw IOException", e);
        } catch (Exception e) {
            logger.error("收发HTTP请求时异常！", e);
        } finally {
            try {
                if (response != null) {
                    EntityUtils.consume(response.getEntity());
                }
            } catch (IOException e) {
            }
        }

        return retStr;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.iwechat.api.http.IHttpUtil#sendGet(java.lang.String, java.util.Map, java.lang.String)
     */
    @Override
    public String sendGet(String url, Map<String, String> urlParams, String sequence) throws Exception {
        long begin = System.currentTimeMillis();
        URI uri = null;
        String retStr = "";
        CloseableHttpResponse response = null;
        try {
            URIBuilder builder = new URIBuilder(url);
            if (urlParams != null) {
                for (Entry<String, String> e : urlParams.entrySet()) {
                    builder = builder.addParameter(URLEncoder.encode(e.getKey(), this.charset), URLEncoder.encode(e.getValue(), this.charset));
                }
            }
            uri = builder.build();
            StringBuffer logbuf = new StringBuffer();
            logbuf.append(sequence);
            logbuf.append(" send_get_to : ");
            logbuf.append(uri.toString());
            logger.info(logbuf.toString());

            HttpGet httpGet = new HttpGet(url);
            response = client.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            if (HttpStatus.SC_OK == statusLine.getStatusCode()) {
                HttpEntity entity = response.getEntity();
                retStr = EntityUtils.toString(entity, charset);
                retStr = retStr == null ? "" : retStr.trim();
            } else {
                JSONObject respJson = this.getJsonerrcode(statusLine);
                respJson.put(ConstEmus.sequence.value(), sequence);
                retStr = respJson.toJSONString();
            }

            logbuf = new StringBuffer();
            logbuf.append(sequence);
            logbuf.append(" response_status : ");
            logbuf.append(statusLine.getStatusCode());
            logbuf.append("; ");
            logbuf.append("consuming_time : ");
            logbuf.append(System.currentTimeMillis() - begin);
            logbuf.append(" ms; ");
            logbuf.append("recive_data : ");
            logbuf.append(retStr);
            logger.info(logbuf.toString());
        } catch (IOException e) {
            throw new HttpException("HttpUtilImpl throw IOException", e);
        } catch (Exception e) {
            logger.error("收发HTTP请求时异常！", e);
        } finally {
            try {
                if (response != null) {
                    EntityUtils.consume(response.getEntity());
                }
            } catch (IOException e) {
            }
        }
        return retStr;
    }

    /**
     * 获得{"errorCode":"status"}样式的错误码
     *
     * @param statusLine
     * @return 返回json字符串
     */
    public JSONObject getJsonerrcode(StatusLine statusLine) {
        JSONObject ret = new JSONObject();
        ret.put("errorCode", statusLine.getStatusCode());
        ret.put("errorMesg", statusLine.getReasonPhrase());
        return ret;
    }

}
